package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.FeeCalTypeEnum;
import cc.rengu.igas.momp.common.enums.McStatusEnum;
import cc.rengu.igas.momp.common.enums.QueryTypeEnum;
import cc.rengu.igas.momp.common.enums.RespCodeEnum;
import cc.rengu.igas.momp.facade.bean.MchntFeeDiscountInfoBean;
import cc.rengu.igas.momp.facade.request.QueryMchntFeeDiscountLimitRequest;
import cc.rengu.igas.momp.facade.response.QueryMchntFeeDiscountLimitResponse;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.bean.PageInfo;
import cc.rengu.oltp.utility.bean.PageResult;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.StringUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商户当前周期手续费优惠限额查询
 *
 * @author liujinan
 * @version 1.0.0
 * @date 2021/6/21 09:19
 */
public class QueryMchntFeeDiscountLimitService extends RadpService {

    /**
     * 法人机构号
     */
    private String globalInstId;
    /**
     * 操作类型
     */
    private String globalQueryType;
    /**
     * 操作人
     */
    private String globalQueryId;
    /**
     * 操作角色
     */
    private String globalQueryRole;
    /**
     * 当前系统日期
     */
    private String globalTimeStamp;
    /**
     * 营销活动商户编号
     */
    private String globalMchntNo;
    /**
     * 营销活动商户名称
     */
    private String globalMchntName;
    /**
     * 交易日期
     */
    private String globalTxnDate;
    /**
     * 操作员所属法人机构
     */
    private String globalQueryOrgId;
    /**
     * 银行行机构代码
     */
    private static final String INST_ID_YT = "816";

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {
            QueryMchntFeeDiscountLimitRequest queryMchntFeeDistcountLimitRequest = new QueryMchntFeeDiscountLimitRequest();
            ConvertUtil.convertOutput(queryMchntFeeDistcountLimitRequest);

            QueryMchntFeeDiscountLimitResponse queryMchntFeeDiscountLimitResponse = new QueryMchntFeeDiscountLimitResponse();
            queryMchntFeeDiscountLimitResponse.setHeader(queryMchntFeeDistcountLimitRequest.getHeader());
            BizResponse<QueryMchntFeeDiscountLimitResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(queryMchntFeeDiscountLimitResponse);

            //报文检查
            messageValidation(queryMchntFeeDistcountLimitRequest);

            rglog.info("机构<{}>在<{}>由<{}>开始查询商户当前周期手续费优惠限额", globalInstId, globalTimeStamp, globalQueryId);

            // 服务调用
            BizResponse<QueryMchntFeeDiscountLimitResponse> bizResponseNew = queryMchntFeeTxnAmtLimitList(queryMchntFeeDistcountLimitRequest, queryMchntFeeDiscountLimitResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());

        } catch (BizException e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 查询商户当前周期手续费优惠限额
     *
     * @param queryMchntFeeDiscountLimitRequest  商户当前周期手续费优惠限额查询接口请求对象
     * @param queryMchntFeeDiscountLimitResponse 商户当前周期手续费优惠限额查询接口应答对象
     * @return cc.rengu.oltp.service.model.BizResponse<cc.rengu.igas.momp.facade.response.QueryMchntFeeDiscountLimitResponse> 营销活动商戶、用戶列表查询接口应答对象
     * @throws BizException 业务异常信息
     * @author liujinan
     * @date 2020/5/27 22:41
     */
    private BizResponse<QueryMchntFeeDiscountLimitResponse> queryMchntFeeTxnAmtLimitList(QueryMchntFeeDiscountLimitRequest queryMchntFeeDiscountLimitRequest, QueryMchntFeeDiscountLimitResponse queryMchntFeeDiscountLimitResponse) throws Exception {

        BizResponse<QueryMchntFeeDiscountLimitResponse> bizResponse = new BizResponse<>();
        //营销活动类型
        PageInfo pageInfo = new PageInfo();
        pageInfo.setPageIndex(Integer.parseInt(queryMchntFeeDiscountLimitRequest.getPageIndex()));
        pageInfo.setPageSize(Integer.parseInt(queryMchntFeeDiscountLimitRequest.getPageSize()));


        List<MchntFeeDiscountInfoBean> mchntFeeDiscountInfoBeanList = new ArrayList<>();
        List<TMStatMfdCriteria> tmStatMfdCriteriaList = new ArrayList<>();


        //银行人员查询
        if (QueryTypeEnum.BANK_QUERY_TYPE.getQueryTypeCode().equals(globalQueryType) || QueryTypeEnum.MCHNT_QYERY_TYPE.getQueryTypeCode().equals(globalQueryType)) {
            rglog.info("判断上送商户号<{}>或商户名称<{}>是否属于上送机构<{}>及下属机构", globalMchntNo, globalMchntName, globalQueryOrgId);
            PageResult pageResult = getMchntInfoByOrgId(globalMchntName, globalMchntNo, globalQueryOrgId, globalTxnDate, pageInfo);
            if (null == pageResult || null == pageResult.getResult() || pageResult.getResult().size() == 0) {
                rglog.info("未查询到商户剩余可优惠额度信息");
            } else {
                mchntFeeDiscountInfoBeanList = pageResult.getResult().stream().map(this::convertMchntFeeDiscountInfo).collect(Collectors.toList());
                mchntFeeDiscountInfoBeanList = mchntFeeDiscountInfoBeanList.stream().filter(item -> !CommonConstant.ZERO_COMMON_CONSTANT.equals(item.getMcNo())).collect(Collectors.toList());
            }
        } else {
            /* 其他查询角色不支持 */
            rglog.error("当前<{}>角色的查询用户<{}>无权限操作数据!", globalQueryRole, globalQueryType);
            throw new BizException(RespCodeEnum.NO_AUTHORIZATION_TO_OPER_ERROR.getRespCode(), RespCodeEnum.NO_AUTHORIZATION_TO_OPER_ERROR.getRespDesc());
        }

        queryMchntFeeDiscountLimitResponse.setMchntFeeDiscountInfoBeanList(mchntFeeDiscountInfoBeanList);
        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        queryMchntFeeDiscountLimitResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        queryMchntFeeDiscountLimitResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        queryMchntFeeDiscountLimitResponse.setPageIndex(queryMchntFeeDiscountLimitRequest.getPageIndex());
        queryMchntFeeDiscountLimitResponse.setPageSize(queryMchntFeeDiscountLimitRequest.getPageSize());
        queryMchntFeeDiscountLimitResponse.setTotalPage(String.valueOf(pageInfo.getTotalPage()));
        queryMchntFeeDiscountLimitResponse.setTotalRows(String.valueOf(mchntFeeDiscountInfoBeanList.size()));

        bizResponse.setResult(queryMchntFeeDiscountLimitResponse);

        return bizResponse;
    }


    /**
     * 请求报文体内容检查
     *
     * @param queryMchntFeeDiscountLimitRequest 商户当前周期手续费优惠限额查询接口请求对象
     * @author liujinan
     * @date 2020/6/22 09:55
     */
    private void messageValidation(QueryMchntFeeDiscountLimitRequest queryMchntFeeDiscountLimitRequest) {

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getHeader().getTransDate())) {
            rglog.error("交易日期必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalTxnDate = queryMchntFeeDiscountLimitRequest.getHeader().getTransDate();
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getHeader().getTransTime())) {
            rglog.error("交易时间必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getHeader().getInstId())) {
            rglog.error("法人机构号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalInstId = queryMchntFeeDiscountLimitRequest.getHeader().getInstId();
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getHeader().getTraceNo())) {
            rglog.error("流水号必须上送!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getQueryType())) {
            rglog.error("操作员类型为空!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalQueryType = queryMchntFeeDiscountLimitRequest.getQueryType();
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getQueryId())) {
            rglog.error("操作员ID为空!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalQueryId = queryMchntFeeDiscountLimitRequest.getQueryId();
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getQueryRole())) {
            rglog.error("操作员角色为空!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalQueryRole = queryMchntFeeDiscountLimitRequest.getQueryRole();
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getQueryOrgId())) {
            rglog.error("操作员所属法人机构为空!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            globalQueryOrgId = queryMchntFeeDiscountLimitRequest.getQueryOrgId();
        }

        if (!StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getMchntNo())) {
            globalMchntNo = queryMchntFeeDiscountLimitRequest.getMchntNo();
        }

        if (!StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getMchntName())) {
            globalMchntName = queryMchntFeeDiscountLimitRequest.getMchntName();
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getPageIndex())) {
            rglog.error("当前页数为空!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(queryMchntFeeDiscountLimitRequest.getPageSize())) {
            rglog.error("页显示记录数为空!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
    }


    /**
     * 获取商户当前周期优惠额度限额
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/28 18:35
     */
    private List<Object> getAllMchntQuotaInfoList(PageInfo pageInfo, String mchntNo, String mchntName) throws Exception {

        List<Object> mchntQuotaInfoList = new ArrayList<>();
        TMStatMfdCriteria tmStatMfdCriteria = new TMStatMfdCriteria();
        tmStatMfdCriteria.setInstId(globalInstId);
        tmStatMfdCriteria.setPeriodStartDate(globalTxnDate);
        tmStatMfdCriteria.setPeriodEndDate(globalTxnDate);

        if (!StringUtil.isNullorEmpty(mchntNo)) {
            tmStatMfdCriteria.setMchntNo(mchntNo);
        }

        if (!StringUtil.isNullorEmpty(mchntName)) {
            tmStatMfdCriteria.setRemark1(mchntName);
        }
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        //不分页
        if (-1 == pageInfo.getPageIndex() || -1 == pageInfo.getPageSize()) {
            mchntQuotaInfoList = tmStatMfdCriteriaMapper.selectMchntQuotaInfoList(tmStatMfdCriteria);
        } else {
            PageResult tmMcMchntInfoPageInfo = tmStatMfdCriteriaMapper.selectMchntQuotaInfoPageList(tmStatMfdCriteria, pageInfo);
            if (null != tmMcMchntInfoPageInfo && null != tmMcMchntInfoPageInfo.getResult()) {
                mchntQuotaInfoList.addAll(tmMcMchntInfoPageInfo.getResult());
            }
        }
        return mchntQuotaInfoList;
    }


    /**
     * 商户当前周期优惠限额转换
     *
     * @param object 手续费减免达标数据统计表
     * @return cc.rengu.igas.momp.facade.bean.MchntQuotaInfoBean 商户当前周期优惠额度对象
     * @author liujinan
     * @date 2020/4/1 10:33
     */
    private MchntFeeDiscountInfoBean convertMchntFeeDiscountInfo(Object object) {

        MchntFeeDiscountInfoBean mchntFeeDiscountInfoBean = new MchntFeeDiscountInfoBean();
        TMStatMfdCriteria tMStatMfdCriteria = (TMStatMfdCriteria) object;
        //商户名称
        mchntFeeDiscountInfoBean.setMchntName(tMStatMfdCriteria.getRemark1());
        //商户号
        mchntFeeDiscountInfoBean.setMchntNo(tMStatMfdCriteria.getMchntNo());
        //商户参与营销活动编号
        mchntFeeDiscountInfoBean.setMcNo(tMStatMfdCriteria.getMcNo());
        //商户优惠额度
        mchntFeeDiscountInfoBean.setMchntFeeDiscount(tMStatMfdCriteria.getMrctDisUpLmtVal());
        //优惠额度结束日期
        String mrctDisUplmtEffDt = tMStatMfdCriteria.getMrctDisUplmtEffDt();
        if (mrctDisUplmtEffDt == null || "".equals(mrctDisUplmtEffDt))
            mrctDisUplmtEffDt = tMStatMfdCriteria.getPeriodEndDate();
        mchntFeeDiscountInfoBean.setTxnAmtLimitEndDate(mrctDisUplmtEffDt);

        //存量商户达标标志
        mchntFeeDiscountInfoBean.setCriteriaFlag(tMStatMfdCriteria.getCriteriaFlag());
        //商户新增标志
        mchntFeeDiscountInfoBean.setNewMchntFlag(tMStatMfdCriteria.getNewMchntFlag());
        //商户参与营销活动的名称
        mchntFeeDiscountInfoBean.setMcName(tMStatMfdCriteria.getRemark2());
        //获取商户剩余优惠额度及已使用的优惠额度
        try {
            mchntFeeDiscountInfoBean = acquireMchntFeeDiscountUsedAndSurplus(mchntFeeDiscountInfoBean, tMStatMfdCriteria.getPeriodStartDate(), tMStatMfdCriteria.getCriteriaValue());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return mchntFeeDiscountInfoBean;
    }

    /**
     * @param mchntName
     * @param mchntNo
     * @param orgId
     * @return
     * @author liujinan
     * @date 2021.8.13
     */
    private PageResult getMchntInfoByOrgId(String mchntName, String mchntNo, String orgId, String txnDate, PageInfo pageInfo) throws Exception {
        TMStatMfdCriteria tmStatMfdCriteria = new TMStatMfdCriteria();
        tmStatMfdCriteria.setRemark1(orgId);
        tmStatMfdCriteria.setMchntNo(mchntNo);
        tmStatMfdCriteria.setRemark2(mchntName);
        tmStatMfdCriteria.setPeriodStartDate(txnDate);
        tmStatMfdCriteria.setPeriodEndDate(txnDate);
        tmStatMfdCriteria.setInstId(globalInstId);
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        return tmStatMfdCriteriaMapper.selectMchntByorgCode(tmStatMfdCriteria, pageInfo);
    }

    /**
     * 获取商户已使用优惠额度及剩余优惠额度
     *
     * @param mchntFeeDiscountInfoBean
     * @return
     * @throws Exception
     * @author liujinan
     * @date 2021.8.13
     */
    private MchntFeeDiscountInfoBean acquireMchntFeeDiscountUsedAndSurplus(MchntFeeDiscountInfoBean mchntFeeDiscountInfoBean, String periodStartDate, String nowCriteriaValue) throws Exception {
        String mchntNo = mchntFeeDiscountInfoBean.getMchntNo();
        String mcNo = mchntFeeDiscountInfoBean.getMcNo();

        //获取营销活动基本信息
        rglog.info("机构<{}>的商户<{}>，开始获取营销活动<{}>的基本信息", globalInstId, mchntNo, mcNo);
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(globalInstId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", globalInstId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MCHNT_FEE_DISCOUNT_MC_LIST_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_FEE_DISCOUNT_MC_LIST_ERROR.getRespDesc());
        }
        /* 增加活动状态判断 */
        String status = tmMcMchntFeeDiscountInfo.getMcStatus();
        if (McStatusEnum.NOT_PUBLISHED.getMcStatusCode().equals(status)) {
            rglog.error("机构<{}>的商户<{}>活动<{}>状态为未发布，无优惠信息!", globalInstId, mchntNo, mcNo);
            mchntFeeDiscountInfoBean.setMcNo(CommonConstant.ZERO_COMMON_CONSTANT);
            return mchntFeeDiscountInfoBean;
        }
        //判断活动是否配置单个商户退出
        /* 需要判断优惠退出条件 */
        String statPeriod = tmMcMchntFeeDiscountInfo.getStatPeriod();
        String newmrctFreeLmtTyp = tmMcMchntFeeDiscountInfo.getNewmrctFreeLmtTyp();
        if (CommonConstant.FEE_EXIT_MC.equals(statPeriod) || CommonConstant.FEE_EXIT_MONTH.equals(statPeriod) ||
                CommonConstant.FEE_EXIT_QUARTER.equals(statPeriod) || CommonConstant.FEE_EXIT_ANNUAL.equals(statPeriod)) {
            rglog.info("法人机构<{}> 手续费优惠营销活动<{}>设置了单个商户退出条件", globalInstId, mcNo, mchntNo);
            /* 单个商户优惠交易笔数上限 */
            BigDecimal quantityLimit = new BigDecimal(tmMcMchntFeeDiscountInfo.getQuantityLimit()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
            /* 单个商户优惠交易金额上限 */
            BigDecimal amountLimit = new BigDecimal(tmMcMchntFeeDiscountInfo.getAmountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /* 单个商户手续费优惠额上限 */
            BigDecimal feeLimit = new BigDecimal(tmMcMchntFeeDiscountInfo.getFeeLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            //计算商户已经消耗的预算值
            TMStatMfdMchnt tmStatMfdMchnt = calAlredyUsedFee(mchntNo, tmMcMchntFeeDiscountInfo, periodStartDate);

            //如果是新商户免手续费的，判断是否是无上限
            if (CommonConstant.MCHNT_NEW_FLAG.equals(mchntFeeDiscountInfoBean.getNewMchntFlag())) {
                BigDecimal newMchntAmountLimit;

                if (null != mchntFeeDiscountInfoBean.getMchntFeeDiscount() && !"".equals(mchntFeeDiscountInfoBean.getMchntFeeDiscount())) {
                    rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值(或没有达标统计表数据的新商户直接使用新商户限额)，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                    newMchntAmountLimit = new BigDecimal(mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                } else {
                    newMchntAmountLimit = new BigDecimal(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());
                }

                rglog.info("法人机构<{}> 手续费优惠营销活动<{}> 商户<{}> 为新商户免手续费参与营销活动，新商户交易额度上限<{}>", globalInstId, mcNo, mchntNo, newMchntAmountLimit);
                if (CommonConstant.BIG_NUMBER.equals(newMchntAmountLimit.toString())) {
                    //优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount("无上限");
                    //剩余优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount("无上限");
                } else {
                    String availAmt;
                    //新增商户免费额度类型
                    if (CommonConstant.ONE_COMMON_CONSTANT.equals(newmrctFreeLmtTyp)) {
                        availAmt = newMchntAmountLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
                    } else {
                        availAmt = newMchntAmountLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
                    }                    //剩余优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(availAmt + "元");
                    //优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount(newMchntAmountLimit.toString() + "元");
                }
                //新增商户免费额度类型
                if (CommonConstant.ONE_COMMON_CONSTANT.equals(newmrctFreeLmtTyp)) {
                    tmStatMfdMchnt.setRemark4(CommonConstant.ONE_COMMON_CONSTANT);
                    //已使用优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTotalAmtAcc() + "元");
                } else {
                    tmStatMfdMchnt.setRemark4(CommonConstant.ZERO_COMMON_CONSTANT);
                    //已使用优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTxnAmtAcc() + "元");
                }
            } else {
                //判断达标标志
                String criteriaFlag = mchntFeeDiscountInfoBean.getCriteriaFlag();
                rglog.info("机构<{}> 营销活动<{}> 商户<{}> 达标统计表达标状态<{}> 0:未达标,1:已达标！", globalInstId, mcNo, mchntNo, criteriaFlag);
                if (!CommonConstant.ONE_COMMON_CONSTANT.equals(criteriaFlag)) {
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(CommonConstant.ZERO_AMOUNT + "元");
                    //预算
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT + "元");
                    //已使用额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(CommonConstant.ZERO_AMOUNT + "元");
                    return mchntFeeDiscountInfoBean;
                }

                if (BigDecimal.ZERO.compareTo(quantityLimit) < CommonConstant.ZERO) {
                    //剩余优惠笔数
                    String availAmt = quantityLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTotalQtyAcc())).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP).toString();
                    //剩余优惠笔数
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(availAmt + "笔");
                    //预算
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount(quantityLimit.toString() + "笔");
                    //已使用额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTotalQtyAcc() + "笔");
                    rglog.info("法人机构<{}> 手续费优惠营销活动<{}> 设置的为优惠笔数限额，剩余额度<{}>", globalInstId, mcNo, availAmt);

                } else if (BigDecimal.ZERO.compareTo(amountLimit) < CommonConstant.ZERO) {

                    if (null != mchntFeeDiscountInfoBean.getMchntFeeDiscount() && !"".equals(mchntFeeDiscountInfoBean.getMchntFeeDiscount())) {
                        rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                        amountLimit = new BigDecimal(mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                    } else {

                    }

                    //剩余优惠交易金额
                    String availAmt = amountLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(availAmt + "元");
                    //预算
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount(amountLimit.toString() + "元");
                    //已使用额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTxnAmtAcc() + "元");
                    rglog.info("法人机构<{}> 手续费优惠营销活动<{}> 设置的为优惠交易金额限额，剩余额度<{}>", globalInstId, mcNo, availAmt);

                } else if (BigDecimal.ZERO.compareTo(feeLimit) < CommonConstant.ZERO) {
                    //剩余手续费优惠额
                    String availAmt = feeLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(availAmt + "元");
                    //预算
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount(feeLimit.toString() + "元");
                    //已使用额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTotalAmtAcc() + "元");
                    rglog.info("法人机构<{}> 手续费优惠营销活动<{}> 设置的为手续费优惠额限额，剩余额度<{}>", globalInstId, mcNo, availAmt);
                } else {
                }
            }

        } else {
            rglog.info("法人机构<{}> 手续费优惠营销活动<{}> 未设置单个商户退出条件，剩余优惠额度使用配置的规则数据计算", globalInstId, mcNo, mchntNo);

            //计算商户已经消耗的预算值
            TMStatMfdMchnt tmStatMfdMchnt = calAlredyUsedFee(mchntNo, tmMcMchntFeeDiscountInfo, periodStartDate);

            //如果是新商户免手续费的，判断是否是无上限
            if (CommonConstant.MCHNT_NEW_FLAG.equals(mchntFeeDiscountInfoBean.getNewMchntFlag())) {
                BigDecimal newMchntAmountLimit = new BigDecimal(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());
                rglog.info("法人机构<{}> 手续费优惠营销活动<{}> 商户<{}> 为新商户免手续费参与营销活动，新商户交易额度上限<{}>", globalInstId, mcNo, mchntNo, newMchntAmountLimit);

                if (null != mchntFeeDiscountInfoBean.getMchntFeeDiscount() && !"".equals(mchntFeeDiscountInfoBean.getMchntFeeDiscount())) {
                    rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值(或没有达标统计表数据的新商户直接使用新商户限额)，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                    newMchntAmountLimit = new BigDecimal(mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                } else {
                }
                if (CommonConstant.BIG_NUMBER.equals(newMchntAmountLimit.toString())) {
                    //剩余优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount("无上限");
                    //预算
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount("无上限");
                } else {
                    String availAmt;
                    //新增商户免费额度类型
                    if (CommonConstant.ONE_COMMON_CONSTANT.equals(newmrctFreeLmtTyp)) {
                        availAmt = newMchntAmountLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
                    } else {
                        availAmt = newMchntAmountLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
                    }                    //剩余优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(availAmt + "元");
                    //预算
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount(newMchntAmountLimit.toString() + "元");
                }
                //新增商户免费额度类型
                if (CommonConstant.ONE_COMMON_CONSTANT.equals(newmrctFreeLmtTyp)) {
                    tmStatMfdMchnt.setRemark4(CommonConstant.ONE_COMMON_CONSTANT);
                    //已使用优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTotalAmtAcc() + "元");
                } else {
                    tmStatMfdMchnt.setRemark4(CommonConstant.ZERO_COMMON_CONSTANT);
                    //已使用优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTxnAmtAcc() + "元");
                }

                return mchntFeeDiscountInfoBean;
            }


            //判断达标标志
            String criteriaFlag = mchntFeeDiscountInfoBean.getCriteriaFlag();
            rglog.info("机构<{}> 营销活动<{}> 商户<{}> 达标统计表达标状态<{}> 0:未达标,1:已达标！", globalInstId, mcNo, mchntNo, criteriaFlag);
            if (!CommonConstant.ONE_COMMON_CONSTANT.equals(criteriaFlag)) {
                mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(CommonConstant.ZERO_AMOUNT + "元");
                //预算
                mchntFeeDiscountInfoBean.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT + "元");
                //已使用额度
                mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(CommonConstant.ZERO_AMOUNT + "元");
                return mchntFeeDiscountInfoBean;
            }

            BigDecimal totalDiscountLimit;

            if (!INST_ID_YT.equals(globalInstId)) {
                //存量商户当前统计值

                //取营销活动规则信息
                List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList = getMchntFeeDiscountMcRuleInfo(globalInstId, mcNo);
                if (null == tmMcMchntFeeDiscountRuleInfoList || tmMcMchntFeeDiscountRuleInfoList.isEmpty()) {
                    /* 未取到营销活动规则信息,本营销活动不可以优惠! */
                    rglog.info("获取机构<{}>的营销活动<{}>优惠规则信息匹配失败!", globalInstId, mcNo);
                    throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
                }

                /* 代码判断匹配到了哪条规则上 */
                TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo;
                BigDecimal criteriaValue = new BigDecimal(nowCriteriaValue).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList1 = new ArrayList<>();
                for (TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo1 : tmMcMchntFeeDiscountRuleInfoList) {

                    BigDecimal floor = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaFloor()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    /* 按照左包右不包原则判断 */
                    if (CommonConstant.ZERO <= criteriaValue.compareTo(floor) && CommonConstant.ZERO > criteriaValue.compareTo(celling)) {
                        tmMcMchntFeeDiscountRuleInfoList1.add(tmMcMchntFeeDiscountRuleInfo1);
                    }
                }

                if (tmMcMchntFeeDiscountRuleInfoList1.isEmpty()) {
                    /* 判断是否是因为当前统计指超过最高档规则上限,是的话按照最高档规则进行优惠 */
                    tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
                    BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    if (CommonConstant.ZERO >= celling.compareTo(criteriaValue)) {
                        rglog.info("当前商户<{}>的达标统计值<{}>超过最高一档规则上限<{}>,按照该档规则计算!", mchntNo, criteriaValue.toString(), celling.toString());
                        tmMcMchntFeeDiscountRuleInfoList1.add(tmMcMchntFeeDiscountRuleInfo);
                    } else {
                        mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(CommonConstant.ZERO_AMOUNT + "元");
                        //预算
                        mchntFeeDiscountInfoBean.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT + "元");
                        //已使用额度
                        mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(CommonConstant.ZERO_AMOUNT + "元");
                        rglog.info("当前商户<{}>的达标统计值<{}>未获取到符合条件的规则，剩余额度直接置为0!", mchntNo, criteriaValue.toString());
                        return mchntFeeDiscountInfoBean;
                    }
                }

                if (null != mchntFeeDiscountInfoBean.getMchntFeeDiscount() && !"".equals(mchntFeeDiscountInfoBean.getMchntFeeDiscount())) {
                    rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                    totalDiscountLimit = new BigDecimal(mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                } else {
                    //计算规则的优惠限制
                    totalDiscountLimit = calculateMchntFeeDiscountLimit(mchntNo, tmMcMchntFeeDiscountRuleInfoList1.get(CommonConstant.ZERO), nowCriteriaValue);
                }

                String ruleNo = tmMcMchntFeeDiscountRuleInfoList1.get(CommonConstant.ZERO).getCalRuleNo();

                rglog.info("机构<{}> 营销活动<{}> 规则总营销额度为<{}>!", globalInstId, mcNo, totalDiscountLimit.toString());
                //如果规则是无上限的，剩余额度为无限大
                if (CommonConstant.BIG_NUMBER.equals(totalDiscountLimit.toString())) {
                    //总优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount("无上限");
                    //剩余优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount("无上限");
                } else {
                    //计算剩余的额度
                    String availAmt;
                    if (FeeCalTypeEnum.TYPE_13.getRuleType().equals(ruleNo)) {
                        availAmt = totalDiscountLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc())).toString();
                    } else {
                        availAmt = totalDiscountLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc())).toString();
                    }
                    //剩余优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(availAmt + "元");
                    //总优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeDiscount(totalDiscountLimit.toString() + "元");
                }
                //判断已使用额度如何取值
                if (FeeCalTypeEnum.TYPE_13.getRuleType().equals(ruleNo)) {
                    //已使用优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTotalAmtAcc() + "元");

                } else {
                    //已使用优惠额度
                    mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTxnAmtAcc() + "元");
                }
            } else {
                rglog.info("当前机构<{}> 为银行，无需获取规则配置信息!", globalInstId);
                //计算剩余的额度
                totalDiscountLimit = new BigDecimal(mchntFeeDiscountInfoBean.getMchntFeeDiscount());
                String availAmt = totalDiscountLimit.subtract(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc())).toString();
                //剩余优惠额度
                mchntFeeDiscountInfoBean.setMchntFeeSurplusDiscount(availAmt + "元");
                //总优惠额度
                mchntFeeDiscountInfoBean.setMchntFeeDiscount(totalDiscountLimit.toString() + "元");
                //已使用优惠额度
                mchntFeeDiscountInfoBean.setMchntFeeUsedDiscount(tmStatMfdMchnt.getTotalAmtAcc() + "元");
            }
        }


        return mchntFeeDiscountInfoBean;
    }

    /**
     * 使用营销活动商户信息对象获取商户手续费优惠类营销活动基本信息
     *
     * @param instId
     * @param mcNo
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountInfo
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2021/8/15
     */
    private TMMcMchntFeeDiscountInfo getMchntFeeDiscountMcInfo(String instId, String mcNo) throws Exception {
        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.selectMchntFeeDiscountMcDetailInfo(instId, mcNo);
    }

    /**
     * 取营销活动规则
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2021/8/15
     */
    private List<TMMcMchntFeeDiscountRuleInfo> getMchntFeeDiscountMcRuleInfo(String instId, String mcNo) throws Exception {

        McRuleInfoMapper mcRuleInfoMapper = new McRuleInfoMapperImpl();
        return mcRuleInfoMapper.selectMchntFeeDiscountRuleInfoList(instId, mcNo);
    }

    /**
     * 查询商户已经使用的优惠额度值
     *
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt
     * @throws Exception
     * @author liujinan
     * @date 2020/9/16
     */
    private TMStatMfdMchnt calAlredyUsedFee(String mchntNo, TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, String periodStartDate) throws Exception {

        String mcNo = tmMcMchntFeeDiscountInfo.getMcNo();

        int batchStatus = CommonConstant.FLAG_NOT_SET;
        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String mcType = tmMcMchntFeeDiscountInfo.getMcType();

        //获取统计数据不判断跑批异常，然后抛出异常，抛出会导致商户服务页面异常

        //查询商户手续费优惠营销活动商户统计表数据
        TMStatMfdMchnt tmStatMfdMchnt = selectNowPeriodDateTMStatMfdMchnt(globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}> 营销活动<{}> 规则<{}> 营销活动商户统计表无数据!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);

            //取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setMchntNo(mchntNo);
            tmStatMfdMchnt.setMcNo(mcNo);

            rglog.info("机构<{}> 手续优惠营销活动<{}> 营销活动商户统计表无数据!", globalInstId, mcNo);

        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + globalInstId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = periodStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", globalInstId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        //查询手续费减免活动商户单日统计表数据
        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        TMStatMfdMchntDay tmStatMfdMchntDay = tmStatMfdMchntDayMapper.selectMchntFeeDiscountMchntDayStatisticsByPK(globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT,
                mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}>的手续优惠营销活动<{}>的规则<{}>对客户营销活动单日统计表数据查询失败!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            //取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }


        tmStatMfdMchnt.setTotalQtyAcc(new BigDecimal(tmStatMfdMchnt.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalQtyAcc())).toString());
        tmStatMfdMchnt.setTotalAmtAcc(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalAmtAcc())).toString());
        tmStatMfdMchnt.setTxnAmtAcc(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnAmtAcc())).toString());

        return tmStatMfdMchnt;
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param mchntNo
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt
     * @throws Exception
     * @author liujinan
     * @date 2020/9/15
     */
    private TMStatMfdMchnt selectNowPeriodDateTMStatMfdMchnt(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 使用主键查询统计信息备份表最新一条数据
     *
     * @param instId
     * @param statType
     * @param statPrimaryKey
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod
     * @throws Exception
     * @author liujinan
     * @date 2021/7/9
     */
    private TMStatBak selectTMStatBakByStatPrimaryKey(String instId, String statType, String statPrimaryKey) throws Exception {

        TMStatBakMapper tmStatBakMapper = new TMStatBakMapperImpl();
        return tmStatBakMapper.selectTMStatBakByStatPrimaryKey(instId, statType, statPrimaryKey);
    }

    /**
     * 使用主键取手续费减免活动商户单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param mchntNo   商户编号
     * @param txnDate   交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchntDay 手续费减免活动商户单日统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/4/20 23:42
     */
    private TMStatMfdMchntDay selectMchntFeeDiscountMchntDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        return tmStatMfdMchntDayMapper.selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt    手续费减免活动商户统计表
     * @param tmStatMfdMchntDay 手续费减免活动商户单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntStatMfdData(TMStatMfdMchnt tmStatMfdMchnt, TMStatMfdMchntDay tmStatMfdMchntDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTotalQtyAcc(new BigDecimal(tmStatMfdMchnt.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTotalAmtAcc(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTxnQtyAcc(new BigDecimal(tmStatMfdMchnt.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTxnAmtAcc(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 根据计算规则计算规则优惠限额
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/16 02:41
     */
    private BigDecimal calculateMchntFeeDiscountLimit(String mchntNo, TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo, String nowCriteriaValue) throws Exception {

        String month = DateUtil.getFutureMonDay(CommonConstant.MINUS_ONE).substring(0, 6);
        rglog.debug("INST_ID=<{}>, MCHNT_NO=<{}>, MONTH=<{}>", globalInstId, mchntNo, month);

        //商户上月日均余额直接取达标统计表中的当前统计值
        String mchntDeposit = nowCriteriaValue;

        BigDecimal TWO = new BigDecimal("2");
        BigDecimal HUNDARD_1 = new BigDecimal("125");
        BigDecimal HUNDARD_5 = new BigDecimal("500");
        BigDecimal THOUSAND_30 = new BigDecimal("30000");
        BigDecimal THOUSAND_50 = new BigDecimal("50000");
        BigDecimal THOUSAND_100 = new BigDecimal("100000");

        BigDecimal deposit = new BigDecimal(mchntDeposit).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal tenThousand = new BigDecimal("10000").setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal discountLimit;

        String calRuleNo = tmMcMchntFeeDiscountRuleInfo.getCalRuleNo();
        if (null != calRuleNo) {
            switch (FeeCalTypeEnum.getByValue(calRuleNo)) {
                case TYPE_0:
                    /* 无上限 */
                    discountLimit = new BigDecimal(CommonConstant.BIG_NUMBER);
                    break;
                case TYPE_1:
                    /* 指定具体数值 */
                    discountLimit = new BigDecimal(tmMcMchntFeeDiscountRuleInfo.getDiscountLimit());
                    break;
                case TYPE_2:
                    /* 上月日均存款万位取整+3万 */
                    discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_3:
                    /* 上月日均存款*2+3万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_4:
                    /* 上月日均存款万位取整+5万 */
                    discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_5:
                    /* 上月日均存款*2+5万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_50);
                    break;
                case TYPE_6:
                    /* 上月日均存款每10万优惠125元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_1);
                    break;
                case TYPE_7:
                    /* 上月日均存款每10万优惠500元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_5);
                    break;
                case TYPE_8:
                    /* 上月日均存款 */
                    discountLimit = deposit;
                    break;
                case TYPE_9:
                    /* 上月日均存款每万元取整*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+3万", calRuleNo);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_10:
                    /* 上月日均存款每万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+5万", calRuleNo);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_11:
                    /* 上月日均存款每十万元*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+3万", calRuleNo);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_12:
                    /* 上月日均存款每十万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+5万", calRuleNo);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_50);
                    break;
                default:
                    discountLimit = new BigDecimal(CommonConstant.ZERO_AMOUNT);
                    rglog.error("营销活动<{}> 规则类型<{}> 手续费优惠限额计算规则类型错误！", tmMcMchntFeeDiscountRuleInfo.getMcNo(), FeeCalTypeEnum.getByValue(calRuleNo));
                    break;
            }
            rglog.info("营销活动<{}> 规则<{}> 规则最高限额<{}>", tmMcMchntFeeDiscountRuleInfo.getMcNo(), tmMcMchntFeeDiscountRuleInfo.getRuleIndex(), discountLimit);
        } else {
            discountLimit = new BigDecimal(CommonConstant.ZERO_AMOUNT);
            rglog.error("营销活动<{}> 手续费优惠计算规则编号为空！", tmMcMchntFeeDiscountRuleInfo.getMcNo());
        }
        return discountLimit;
    }
}
